package arithmetic.thread;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import com.google.common.util.concurrent.ThreadFactoryBuilder;

/**
 * execute和submit都属于线程池的方法，execute只能提交Runnable类型的任务，而submit既能提交Runnable类型任务也能提交Callable类型任务。
 * execute会直接抛出任务执行时的异常，submit会吃掉异常，可通过Future的get方法将任务执行时的异常重新抛出。
 * 原文链接：https://blog.csdn.net/mryang125/article/details/81879096
 * @author jiangfeng
 * Created on 2020-04-02
 */
public class TestExcutors {
    public static void main(String[] args) throws InterruptedException {
         int threads= Runtime.getRuntime().availableProcessors();

        ThreadFactory tf = new ThreadFactoryBuilder().setUncaughtExceptionHandler((t, e) -> {
            System.out.println("多线程处理校验时异常:"+t.getName()+" e"+e.getMessage());
           // log.error("多线程处理校验时异常", e);
            // exceptions.add(new BatchProcessExcelException("入库出错:" + e.getMessage()));
        }).build();

        ThreadPoolExecutor executor = new ThreadPoolExecutor(threads*2, threads * 2, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(20),tf);

        long l =System.currentTimeMillis();
        int a= 18;
        CountDownLatch downLatch = new CountDownLatch(a);
        for (int i = 0; i < a; i++) {
            int finalI = i;
            executor.execute(() -> {
                try {
                    doSomething();
                    if (finalI%2 ==0) {
                        System.out.println(1 / 0);
                    }
                    System.out.println("完成:" + finalI);
                } finally {
                    downLatch.countDown();
                }
            });
        }
        downLatch.await();
        System.out.println("全部完成:"+(System.currentTimeMillis()-l));
        executor.shutdown();

    }

    public static void doSomething(){
        System.out.println("进入"+Thread.currentThread().getName());
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("完成"+Thread.currentThread().getName());
    }
}
